using MediatR;
using Microsoft.Extensions.Logging;
using S.O.Api.Write.Application.Command.Medical;
using S.O.Domain.Medical;
using S.O.ErrorCode;
using S.O.Interstructrue.Base;
using Microsoft.EntityFrameworkCore;

namespace S.O.Api.Write.Application.Handler.Medical
{
    /// <summary>
    /// 创建收费记录处理器
    /// 负责处理门诊收费业务逻辑，包括费用结算、付费状态更新等
    /// </summary>
    public class CreateChargeHandler : IRequestHandler<CreateChargeCommand, APIResult<string>>
    {
        /// <summary>
        /// 挂号记录仓储
        /// </summary>
        private readonly IBaseRepository<RegistrationModel> _registrationRepository;
        
        /// <summary>
        /// 处方药品明细仓储
        /// </summary>
        private readonly IBaseRepository<PrescriptionMedicineModel> _prescriptionMedicineRepository;
        
        /// <summary>
        /// 处方信息仓储
        /// </summary>
        private readonly IBaseRepository<PrescriptionModel> _prescriptionRepository;
        
        /// <summary>
        /// 日志记录器
        /// </summary>
        private readonly ILogger<CreateChargeHandler> _logger;

        /// <summary>
        /// 构造函数，通过依赖注入初始化所需服务
        /// </summary>
        /// <param name="registrationRepository">挂号记录仓储</param>
        /// <param name="prescriptionMedicineRepository">处方药品明细仓储</param>
        /// <param name="prescriptionRepository">处方信息仓储</param>
        /// <param name="logger">日志记录器</param>
        public CreateChargeHandler(
            IBaseRepository<RegistrationModel> registrationRepository,
            IBaseRepository<PrescriptionMedicineModel> prescriptionMedicineRepository,
            IBaseRepository<PrescriptionModel> prescriptionRepository,
            ILogger<CreateChargeHandler> logger)
        {
            _registrationRepository = registrationRepository;
            _prescriptionMedicineRepository = prescriptionMedicineRepository;
            _prescriptionRepository = prescriptionRepository;
            _logger = logger;
        }

        /// <summary>
        /// 处理创建收费记录请求
        /// </summary>
        /// <param name="request">创建收费记录命令</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>收费单号</returns>
        public async Task<APIResult<string>> Handle(CreateChargeCommand request, CancellationToken cancellationToken)
        {
            try
            {
                _logger.LogInformation("开始处理收费请求，患者ID：{PatientId}，挂单号：{RegistrationNo}，总金额：{TotalAmount}", 
                    request.PatientId, request.RegistrationNo, request.TotalAmount);
                
                // 1. 验证挂号记录是否存在
                var registration = _registrationRepository.GetALL()
                    .FirstOrDefault(r => r.RegistrationNo == request.RegistrationNo && 
                                            r.PatientId == request.PatientId && 
                                            r.IsEnable == true);
                
                if (registration == null)
                {
                    _logger.LogWarning("挂号记录不存在，患者ID：{PatientId}，挂单号：{RegistrationNo}", request.PatientId, request.RegistrationNo);
                    return new APIResult<string>
                    {
                        Code = APIEnums.Error,
                        Msg = "挂号记录不存在",
                        Data = string.Empty
                    };
                }
                
                // 2. 验证收费金额
                if (request.TotalAmount <= 0)
                {
                    return new APIResult<string>
                    {
                        Code = APIEnums.Error,
                        Msg = "收费金额必须大于0",
                        Data = string.Empty
                    };
                }
                
                if (request.PaidAmount < request.TotalAmount)
                {
                    return new APIResult<string>
                    {
                        Code = APIEnums.Error,
                        Msg = "支付金额不足",
                        Data = string.Empty
                    };
                }
                
                // 3. 更新处方药品的付费状态
                foreach (var item in request.ChargeItems)
                {
                    if (!string.IsNullOrEmpty(item.PrescriptionId))
                    {
                        var medicines = _prescriptionMedicineRepository.GetALL()
                            .Where(pm => pm.PrescriptionId == item.PrescriptionId && 
                                        pm.Id.ToString() == item.MedicineId)
                            .ToList();
                        
                        foreach (var medicine in medicines)
                        {
                            // 注意：PrescriptionMedicineModel可能没有IsPaid和PaidTime字段
                            // 这里只是示例，实际应该根据业务需求处理付费状态
                            medicine.UpdateTime = DateTime.Now;
                            _prescriptionMedicineRepository.Update(medicine);
                        }
                    }
                }
                
                // 4. 更新挂号记录的付费状态
                registration.Status = "已付费";
                _registrationRepository.Update(registration);
                
                // 5. 生成收费单号
                var chargeNo = GenerateChargeNo();
                
                _logger.LogInformation("收费处理成功，收费单号：{ChargeNo}，患者ID：{PatientId}", chargeNo, request.PatientId);
                
                return new APIResult<string>
                {
                    Code = APIEnums.Success,
                    Msg = "收费成功",
                    Data = chargeNo
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "处理收费请求时发生异常，患者ID：{PatientId}，挂单号：{RegistrationNo}", 
                    request.PatientId, request.RegistrationNo);
                return new APIResult<string>
                {
                    Code = APIEnums.Error,
                    Msg = "收费处理失败",
                    Data = string.Empty
                };
            }
        }
        
        /// <summary>
        /// 生成收费单号
        /// 格式：CH + 年月日 + 6位序号
        /// </summary>
        /// <returns>收费单号</returns>
        private string GenerateChargeNo()
        {
            var dateStr = DateTime.Now.ToString("yyyyMMdd");
            var random = new Random();
            var sequence = random.Next(100000, 999999);
            return $"CH{dateStr}{sequence}";
        }
    }
}